package GameEngine;

import java.io.*;
import java.util.Observable;
import java.util.Observer;

/**
 * This class is used for input specific 
 * error handling.
 */
@SuppressWarnings("serial")
class InputException extends Exception
{

    /**
     * The default constructor.
     */
    public InputException()
    {
        super();
    }

    /**
     * Constructor that needs a specific error message.
     * 
     * @param msg Message that should be output.
     */
    public InputException(String msg)
    {
        super(msg);
    }
}

/**
 * The Input class reads input from the command line.
 * This is very helpful, when you are dealing with short programs to
 * make oneself more familiar with different algorithms.
 *
 */
public class Input implements Observer
{

    /**
     * Reads input string from the command line.
     *
     * @return s String that was read from the prompt
     */
    public String readln() throws InputException
    {
        try
        {
            //init input-buffered-reader
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(System.in));


            // return input
            return in.readLine();
        }
        
        catch (IOException e)
        {
            throw new InputException("Error - Please try again.");
        }
    }

    /**
     * Reads input string from command line after a prompt.
     *
     * @param prompt The text in front of the prompt
     * @return s String that was read from the prompt
     * @see #readln()
     */
    public String readln(String prompt) throws InputException
    {
        // print out prompt
        System.out.print(prompt);

        return readln();
    }

    /**
     * Reads an integer from the command line.
     *
     * @return s Integer that was read from the prompt
     * @see #readln()
     */
    public int readInt() throws InputException
    {
        // init return val
        int input = 0;

        try
        {
            // read and cast input
            input = Integer.valueOf(readln()).intValue();
        }
        
        catch (NumberFormatException e)
        {
            // print error message
            throw new InputException("Invalid input!");
        }

        return input;
    }

    /**
     * Reads integer input from command line after a prompt.
     *
     * @param prompt The text in front of the prompt
     * @return s Integer that was read from the prompt
     * @see #readln()
     * @see #readInt()
     */
    public int readInt(String prompt) throws InputException
    {
        // print out prompt
        System.out.print(prompt);

        return readInt();
    }

    /**
     * Reads a float input from command line.
     *
     * @return s Integer that was read from the prompt
     * @see #readln()
     */
    public float readFloat() throws InputException
    {
        // init return val
        float input = 0;

        try
        {
            // read and cast input
            input = Float.valueOf(readln()).floatValue();
        }
        
        catch (NumberFormatException e)
        {
            // print error message
            throw new InputException("Invalid input!");
        }

        return input;
    }

    /**
     * Reads float input from command line after a prompt.
     *
     * @param prompt The text in front of the prompt
     * @return s Integer that was read from the prompt
     * @see #readln()
     * @see #readFloat()
     */
    public float readFloat(String prompt) throws InputException
    {
        // print out prompt
        System.out.print(prompt);

        return readFloat();
    }

    /**
     * Reads double input from command line.
     *
     * @return s Double that was read from the prompt
     * @see #readln()
     */
    public double readDouble() throws InputException
    {
        double input = 0;

        try
        {
            // read and cast input
            input = Double.valueOf(readln()).doubleValue();
        }
        
        catch (NumberFormatException e)
        {
            // print error message
            throw new InputException("Invalid input!");
        }

        return input;
    }

    /**
     * Reads double input from command line after a prompt.
     *
     * @param prompt The text in front of the prompt
     * @return s Integer that was read from the prompt
     * @see #readln()
     * @see #readDouble()
     */
    public double readDouble(String prompt) throws InputException
    {
        // print out prompt
        System.out.print(prompt);

        return readDouble();
    }

    /**
     * Reads an integer array from the command line.
     *
     * @param size Size of the required array
     * @param del Delimiter that should be used
     * @return arr Integer array that was read from the prompt
     * @see #readln()
     */
    public int[] readIntArray(int size, String del) throws InputException
    {

        // init return value
        int ret[] = new int[size];

        // read string from command line
        String s = readln();

        // if the string is equal with "exit", "Exit", "quit", "Quit" the game will be quit
        if(s.equals("exit") || s.equals("quit") || s.equals("Exit") || s.equals("Quit"))
        {
            System.out.print("Are you sure you want to quit this game ? (yes) ");
            String answer = readln();

            if( answer.equalsIgnoreCase("yes") )
            {
                System.out.println("Program exit by player!\n");
                System.exit(1);
            }
            
            else
            {
                System.out.println("Program will be continued...\n");
            }
        }
        
        // player gives up
        if( s.equals("") )
        {
            System.out.println("Do you really want to give up? (yes)");
            String answer = readln();
            
            if( answer.equalsIgnoreCase("yes") )
            {
                return null;
            }
            
            else
            {
                System.out.println("Programm will be continued...\n");
            }
        }

        // split arguments
        String tmp[] = s.split(del);
        
        // check number of arguments
        if( tmp.length != size )
        {
            throw new InputException("Invalid number of arguments!");
        }

        // convert to integer array
        for(int i = 0; i < size; i++)
        {
            try
            {
                // read and cast input
                ret[i] = Integer.valueOf(tmp[i]).intValue();
            }
            
            catch (NumberFormatException e)
            {
                // print error message
                throw new InputException("Invalid input!");
            }
        }

        return ret;
    }

    /**
     * Reads double input from command line after a prompt.
     *
     * @param size Size of the required array
     * @param del Delimiter that should be used
     * @param prompt The text in front of the prompt
     * @return arr Integer array that was read from the prompt
     * @see #readln()
     * @see #readIntArray(int, String)
     */
    public int[] readIntArray(int size, String del, String prompt) throws InputException
    {
        // print out prompt
        System.out.print(prompt);

        return this.readIntArray(size, del);
    }

	@Override
	public void update(Observable arg0, Object arg1) {
		// TODO Auto-generated method stub
		
		
	}
}
